package icu.zlz.emqx.service.impl;

import com.alibaba.nacos.shaded.com.google.gson.JsonArray;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import icu.zlz.common.core.exception.ServiceException;
import icu.zlz.common.core.utils.StringUtils;
import icu.zlz.common.core.web.domain.AjaxResult;
import icu.zlz.emqx.domain.MqttAcl;
import icu.zlz.emqx.domain.MqttUserOnline;
import icu.zlz.emqx.utils.Signature;
import okhttp3.*;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ObjectUtils;


import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

/**
 * @author zangsheng
 */
@Service
public class MqttAuthService {

    @Value("${mqttAuth.url}")
    private String baseUrl;
    @Value("${mqttAuth.appId}")
    private String appId;
    @Value("${mqttAuth.appSecret}")
    private String appSecret;
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private final OkHttpClient client = new OkHttpClient();

    private static final String USER_API = "/api/emqx/user";
    private static final String ACL_API = "/api/emqx/acl";
    private static final String USER_ONLINE_API = "/api/emqx/userOnline";
    private static final MediaType MEDIA_TYPE_JSON = MediaType.get("application/json; charset=utf-8");

    private Request.Builder getBuilder(String url, String data) {

        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);


        Request.Builder builder = new Request.Builder();
        builder.url(baseUrl + url);
        builder.header("Content-Type", "application/json");
        builder.header("appId", appId);
        builder.header("timestamp", timestamp);
        String signature = Signature.signWithHmacSha1(appSecret, url, data, timestamp);
        if (!StringUtils.hasText(signature)) {
            throw new ServiceException("签名失败");
        }
        builder.header("signature", signature);
        System.out.println(baseUrl + url);
        System.out.println(appId);
        System.out.println(timestamp);
        System.out.println(signature);
        return builder;

    }

    private AjaxResult getResponse(Request.Builder builder) {
        try {
            try (Response response = client.newCall(builder.build()).execute()) {
                if (response.body() != null) {
                    if (!response.isSuccessful()) {
                        return AjaxResult.error(response.code(), "HTTP request failed with  msg: " + response.body().toString());
                    }
                    return OBJECT_MAPPER.readValue(response.body().string(), AjaxResult.class);
                } else {
                    return AjaxResult.error("Response body is null");
                }
            }

        } catch (IOException e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    public AjaxResult addUser(String username, String password, String userUid) {

        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("username", username);
        jsonObject.addProperty("password", password);
        jsonObject.addProperty("userUid", userUid);
        //盐值
        jsonObject.addProperty("salt", "salt");

        Request.Builder builder = getBuilder(USER_API, jsonObject.toString());
        builder.post(RequestBody.create(jsonObject.toString(), MEDIA_TYPE_JSON));
        return getResponse(builder);

    }

    public AjaxResult editGroupPrefix(String oldName, String newName) {
        Request.Builder builder = getBuilder(ACL_API + "/topic/" + oldName + "/" + newName, null);
        builder.get();
        return getResponse(builder);

    }


    /**
     * String uid, String username,String password
     *
     * @return
     */
    public AjaxResult editUser(JsonObject data) {
        Request.Builder builder = getBuilder(USER_API, data.toString());
        builder.put(RequestBody.create(data.toString(), MEDIA_TYPE_JSON));
        return getResponse(builder);

    }


    public AjaxResult deleteAclByClientIds(String[] clientIds) {
        Request.Builder builder = getBuilder(ACL_API + "/" + String.join(",", clientIds), null);
        builder.delete();
        return getResponse(builder);
    }


    public AjaxResult addAcl(String groupUid, List<MqttAcl> mqttAcl) {

        JsonArray jsonArray = new JsonArray();

        for (MqttAcl acl : mqttAcl) {
            JsonObject jsonObject = new JsonObject();
            jsonObject.addProperty("action", acl.getAction());
            jsonObject.addProperty("clientId", acl.getClientId());
            jsonObject.addProperty("topicUid", acl.getTopicUid());
            jsonObject.addProperty("topic", acl.getTopic());
            jsonObject.addProperty("permission", acl.getPermission());
            jsonArray.add(jsonObject);
        }


        Request.Builder builder = getBuilder(ACL_API + "/" + groupUid, jsonArray.toString());
        builder.post(RequestBody.create(jsonArray.toString(), MEDIA_TYPE_JSON));
        return getResponse(builder);

    }


    public AjaxResult editAclTopicByUid(String topicUid, String topic) {
        String encodedString;
        try {
            encodedString = URLEncoder.encode(topic, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new ServiceException("URLEncoder异常");
        }
        Request.Builder builder = getBuilder(ACL_API + "?topicUid=" + topicUid + "&topic=" + encodedString, null);
        builder.get();
        return getResponse(builder);
    }


    public AjaxResult addUserStatus(List<MqttUserOnline> mqttUserOnline) {
        JsonArray jsonArray = new JsonArray();
        for (MqttUserOnline online : mqttUserOnline) {
            JsonObject jsonObject = new JsonObject();
            jsonObject.addProperty("online", online.getOnline());
            jsonObject.addProperty("clientId", online.getClientId());
            jsonObject.addProperty("deviceUid", online.getDeviceUid());
            jsonObject.addProperty("userUid", online.getUserUid());
            jsonArray.add(jsonObject);
        }
        Request.Builder builder = getBuilder(USER_ONLINE_API, jsonArray.toString());
        builder.post(RequestBody.create(jsonArray.toString(), MEDIA_TYPE_JSON));
        System.out.println(jsonArray.toString());
        return getResponse(builder);
    }


    public AjaxResult editUserStatus(List<MqttUserOnline> mqttUserOnline) {
        JsonArray jsonArray = new JsonArray();
        for (MqttUserOnline online : mqttUserOnline) {
            JsonObject jsonObject = new JsonObject();
            if (!ObjectUtils.isEmpty(online.getOnline())) {
                jsonObject.addProperty("online", online.getOnline());

            }
            if (StringUtils.hasText(online.getClientId())) {
                jsonObject.addProperty("clientId", online.getClientId());

            }
            jsonObject.addProperty("deviceUid", online.getDeviceUid());
            jsonArray.add(jsonObject);
        }
        Request.Builder builder = getBuilder(USER_ONLINE_API, jsonArray.toString());
        builder.put(RequestBody.create(jsonArray.toString(), MEDIA_TYPE_JSON));
        return getResponse(builder);
    }

}
